#include "Canva.h"
#include <math.h>
#include <CImg.h>
#include <Magick++.h>
#include "externalArg.h"
#include "CommonDepence.h"
#pragma comment(lib, "E:\\code\\c++\\RandomCA\\RandomCA\\x64\\Release\\GPUCompute.lib")
using std::cout;
int rca::restart = 0;
COLORREF rca::keyColors[] = { RGB(0,0,0),RGB(255,0,0),RGB(0,255,0),RGB(0,0,255),RGB(255,255,0),RGB(255,0,255),RGB(0,255,255),RGB(255,255,255),RGB(255,0x99,255),RGB(70,130,180), };
COLORREF rca::presentColor = keyColors[0];
CImg<char> OutEnlarge(int multiple, CImg<char>* img, int Width, int Height)
{
	CImg<char> bigImg(Width, Height, 1, 3, 0);
	for (int ix = 0; ix < Width/multiple; ix++) {
		for (int iy = 0; iy < Height/multiple; iy++) {
			char color[3] = { (*img)(ix,iy,0,0),(*img)(ix,iy,0,1),(*img)(ix,iy,0,2) };
			bigImg.draw_rectangle(ix * multiple, iy * multiple, (ix + 1) * multiple, (iy + 1) * multiple, color);
		}
	}
	return bigImg;
}

CImg<char> Canva::sampling(int width, int height)
{
	CImg<char> smallImg(Width / width+1 , Height / height + 1,1,3,0);
	for (int ix = 0; ix <= Width/width; ix++) {
		for (int iy = 0; iy <= Height/height; iy++) {
			smallImg(ix, iy, 0, 0) = (*img)(ix * width, iy * height,0, 0);
			smallImg(ix, iy, 0, 1) = (*img)(ix * width, iy * height, 0, 1);
			smallImg(ix, iy, 0, 2) = (*img)(ix * width, iy * height, 0,2);
		}
	}
	return smallImg;
}

CImg<char> Canva::enlarge(int multiple)
{
	CImg<char> bigImg(Width * multiple, Height * multiple,1,3,0);
	for (int ix = 0; ix < Width; ix++) {
		for (int iy = 0; iy < Height; iy++) {
			char color[3] = { (*img)(ix,iy,0,0),(*img)(ix,iy,0,1),(*img)(ix,iy,0,2) };
			bigImg.draw_rectangle(ix * multiple, iy * multiple, (ix + 1) * multiple, (iy + 1) * multiple,color);
		}
	}
	return bigImg;
}

void Canva::changeCImg(int x, int y, COLORREF color)
{
	(*img)(x, y,0, 0) = GetRValue(color);
	(*img)(x, y, 0, 1) = GetGValue(color);
	(*img)(x, y, 0, 2) = GetBValue(color);
}

Canva::Canva(int width, int height, bool isXY)
{
	if (isXY) {
		img = new CImg<char>(width * 2, height * 2,1,3,0);
		newimg = new CImg<char>(width * 2, height * 2,1,3,0);
		Width = width * 2;
		X = width;
		Height = height * 2;
		Y = height;
	}
	else {
		img = new CImg<char>(width, height,1,3,0);
		newimg = new CImg<char>(width, height,1,3,0);
		Width = width;
		X = width / 2;
		Height = height;
		Y = height / 2;
	}
	penSize = 1;
	pause = 0;
}
Canva::~Canva()
{
	delete img;
	delete newimg;
	delete uc;
}
Canva::Canva(CImg<char> _img)
{
	*img = _img;
}

void Canva::initDisplay(const char* const title, unsigned int normalization , bool is_fullscreen , bool is_closed )
{
	screen = CImgDisplay((*img), title, normalization, is_fullscreen, is_closed);
}

void rca::ChangeColorKey() {
	std::ifstream file = std::ifstream("./KeysConfig.txt");
	bool success = file.is_open();
	int useHex = 0;
	file >> useHex;
	if (useHex) {
		file >> std::hex;
	}
	for (int i = 0; i < 9; i++) {
		int R, G, B;
		file >> R;
		file >> G;
		file >> B;
		keyColors[i] = RGB(R, G, B);
	}
	file.close();
}

void Canva::checkOperation(int multiple)
{
	rca::ChangeColorKey();
	bool iskey = screen.is_key();
	unsigned int key=screen.key();
   if (key <= cimg::keyPAD9 && key >= cimg::keyPAD0) {
	   rca::ChangeColorKey();
		rca::presentColor = rca::keyColors[key - cimg::keyPAD0];
		screen.set_key();
	}
   if (key <= cimg::key9 && key >= cimg::key0) {
	   penSize = key - cimg::key0;
	   screen.set_key();
   }
   if (screen.is_keyESC()) {
	   pause = pause ^ 1;
	   screen.set_key();
   }
   if (screen.button() & 2) {
	   int mx = screen.mouse_x();
	   int my = screen.mouse_y();
	   for (int ix = -penSize; ix <= penSize; ix++) {
		   for (int iy = -penSize; iy <= penSize; iy++) {
			   int x = mx / multiple + ix;
			   int y = my / multiple + iy;
			   if (x >= 0 && x < Width && y >= 0 && y < Height) {
				   AddChange(x, y, rca::presentColor);
			   }
		   }
	   }
   }
   if (screen.button() & 4) {
	   rca::restart = 1;
   }
}

void Canva::putPixelXY(int x, int y,COLORREF color)
{
	changeCImg(x, y, color);
}

void Canva::putRectangle(int x, int y, int width, int height, COLORREF color)
{
	char cimgcolors[3]{ GetRValue(color),GetGValue(color) ,GetBValue(color) };
	(*img).draw_rectangle(x, y, x + width, y + height, cimgcolors, 1);
}

COLORREF Canva::getPixelXY(int x, int y)
{
	return RGB(0, 0, 0);
}

void Canva::AddChange(int x, int y, COLORREF color)
{
	mtx.lock();
	Changes.push(AChange(x, y, color));
	mtx.unlock();
}

void Canva::DoChange()
{
	mtx.lock();
	while (!Changes.empty()) {
		AChange change = Changes.front();
		changeCImg(change.x, change.y, change.color);
		Changes.pop();
	}
	mtx.unlock();
}

void Canva::updateWithIMG(CImg<char> Img)
{
	(* img) = Img;
}

//xy
void Canva::initWithSupplier(COLORREF(*s)())
{
	for (int i = 0; i < Width * Height; i++) {
		COLORREF color = (*s)();
		(*img)(i % Width, i / Width, 0, 0) = GetRValue(color);
		(*img)(i % Width, i / Width,0, 1) = GetGValue(color);
		(*img)(i % Width, i / Width, 0, 2) = GetBValue(color);
	}
}

void Canva::initWithFunction(COLORREF(*s)(int x,int y,int width,int height))
{
	for (int i = 0; i < Width * Height; i++) {
		COLORREF color = (*s)(i % Width, i / Width, Width, Height);
		changeCImg(i % Width, i / Width, color);
	}
}

void Canva::initWithSupplierLarge(COLORREF(*s)(),int multiple)
{
	CImg<char> Small = sampling(multiple, multiple);
	Canva smallImg = Canva(Small);
	smallImg.initWithSupplier(s);
	*img = smallImg.enlarge(multiple);
}

void Canva::initWithFunctionLarge(COLORREF(*s)(int x, int y,int width,int height), int multiple)
{
	CImg<char> Small = sampling(multiple, multiple);
	Canva smallImg = Canva(Small);
	smallImg.initWithFunction(s);
	*img = smallImg.enlarge(multiple);
}


void Canva::updateClassInit(int multiple)
{
	ucm = multiple;
	if (multiple == 1) {
		uc = new ImgUpdater(img);
	}
	else {
		CImg<char> Small = sampling(multiple, multiple);
		uc = new ImgUpdater(&Small);
	}
}

void Canva::updateClass() {
	while(pause){
		Sleep(10);
	}
	uc->update();
	mtx.lock();
	while (!Changes.empty()) {
		AChange change = Changes.front();
		uc->ChangePixel(change.x, change.y, change.color);
		Changes.pop();
	}
	mtx.unlock();
}

void Canva::updateFromClass() {
	if (ucm == 1) {
		*img = uc->getImg();
	}
	else {
		CImg<char> temp = uc->getImg();
		*img = OutEnlarge(ucm,&temp,Width,Height);
	}
}

CImg<char>* Canva::getIMG()
{
	return img;
}
